﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.IO;

namespace Ahmad.A.Ousman.WindowsProxy.Common
{
    [Serializable]
    public class Proxy
    {
        #region Constants
        public const String LOCAL_ADDRESSES = "<local>";
        public const String INTERNET_SETTINGS = @"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
        public const String PROXY_SERVER = "ProxyServer";
        public const String PROXY_EXCEPTIONS = "ProxyOverride";
        public const String PROXY_ENABLED = "ProxyEnable";
        #endregion

        public Proxy()
        {
            DnsDomain = string.Empty;
            EnableProxyServer = false;
            ProxyServer = string.Empty;
            ProxyExceptions = string.Empty;
            ProxyUserName = string.Empty;
            ProxyPassword = string.Empty;
        }

        #region Properties
        public String DnsDomain { get; set; }
        public bool EnableProxyServer { get; set; }
        public String ProxyServer { get; set; }
        public String ProxyExceptions { get; set; }
        public String ProxyUserName { get; set; }
        public String ProxyPassword { get; set; }
        public Boolean IsNull { get { return String.IsNullOrEmpty(DnsDomain); } }
        #endregion

        #region Methods
        public override bool Equals(object obj)
        {
            var proxy = obj as Proxy;
            return proxy != null && DnsDomain.Equals(proxy.DnsDomain, StringComparison.InvariantCultureIgnoreCase);
        }
        public override int GetHashCode()
        {
            return DnsDomain.GetHashCode();
        }
        #endregion
    }

    [Serializable]
    public class ProxyCollection : IList<Proxy>
    {
        #region Properties
        String DataSourceFileName { get; set; }
        List<Proxy> Items { get; set; }
        XmlDocument ItemsXmlDocument { get; set; }
        #endregion

        #region Constructor
        public ProxyCollection(String dataSourceFileName)
        {
            //Debugger.Break();
            Items = new List<Proxy>();
            DataSourceFileName = dataSourceFileName;
            ItemsXmlDocument = new XmlDocument();
            var info = new FileInfo(DataSourceFileName);
            if (info.Exists)
            {
                ItemsXmlDocument.Load(DataSourceFileName);
                Items = ItemsXmlDocument.OuterXml.DeserializeXmlToObject<List<Proxy>>();
            }
            else
            {
                Save();
            }
        }
        #endregion

        #region Public Methods
        public void Save()
        {
            ItemsXmlDocument.LoadXml(Items.SerializeObjectToXml());
            ItemsXmlDocument.Save(DataSourceFileName);
        }

        public Proxy Find(Predicate<Proxy> predicate)
        {
            return Items.Find(predicate);
        }

        public int IndexOf(Proxy item)
        {
            return Items.IndexOf(item);
        }

        public void Insert(int index, Proxy item)
        {
            Items.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            Items.RemoveAt(index);
        }

        public Proxy this[int index]
        {
            get
            {
                return Items[index];
            }
            set
            {
                if (index < Items.Count)
                {
                    Items[index] = value;
                }
                else
                {
                    Items.Add(value);
                }
            }
        }

        public void Add(Proxy item)
        {
            var oldItem = Items.Find(match => match.DnsDomain.Equals(item.DnsDomain, StringComparison.InvariantCultureIgnoreCase));
            if (oldItem == null)
            {
                Items.Add(item);
            }
            else
            {
                oldItem.Clone(item);
            }
        }

        public void Clear()
        {
            Items.Clear();
        }

        public bool Contains(Proxy item)
        {
            return Items.Contains(item);
        }

        public void CopyTo(Proxy[] array, int arrayIndex)
        {
            Items.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return Items.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(Proxy item)
        {
            return Items.Remove(item);
        }

        public void RemoveAll(Predicate<Proxy> match)
        {
            Items.RemoveAll(match);
        }

        public IEnumerator<Proxy> GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Items.GetEnumerator();
        }
        #endregion
    }
}
